package httpstunnel

import (
	"context"
	"encoding/binary"
	"github.com/go-acme/lego/log"
	"github.com/mholt/certmagic"
	"net"
	"net/http"
	"net/http/httputil"
	"sync"
	"sync/atomic"
)

func runHttps(domain []string, addr string, port int) error {
	c := certmagic.NewDefault()
	c.Email = "admin@clearcode.cn"
	c.Agreed = true
	c.CA = certmagic.LetsEncryptProductionCA

	log.Println("domain: ", domain)
	err := c.Manage(domain)
	if err != nil {
		return err
	}

	mux := new(MyMux)
	return http.ListenAndServe(":80", c.HTTPChallengeHandler(mux))
}

type MyMux struct {
	http.ServeMux
}

var (
	respWriter       = sync.Map{}
	respIndex  int64 = 0
)

func (MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	x, _ := httputil.DumpRequest(r, false)
	log.Println("new request: ", string(x))

	var domain = ""
	if r.Host != "" {
		domain = r.Host
	}

	if domain == "" {
		domain = r.URL.Host
	}

	conn, ok := registryDomain.Load(domain)
	if !ok {
		// 404
		http.Error(w, "404 Not Found", 404)
		return
	}

	var ch = make(chan struct{})
	ctx := context.WithValue(context.Background(), "w", w)
	ctx = context.WithValue(ctx, "chan", ch)

	idx := atomic.AddInt64(&respIndex, 1)
	respWriter.Store(idx, ctx)

	body, err := httputil.DumpRequestOut(r, true)

	if err != nil {
		http.Error(w, "internel server error: "+err.Error(), 503)
		return
	}

	var b = make([]byte, 4)
	binary.BigEndian.PutUint64(b, uint64(idx))

	newBody := append(body, b...)

	_, err = conn.(net.Conn).Write(tcpWriteWrap(CmdProxy, newBody))

	if err != nil {
		http.Error(w, "internel server error: "+err.Error(), 503)
		return
	}

	<-ch
}
